package com.cskaoyan.javase.object._8callback;

/**
 * 在小明回答问题的方法中
 * 将对象传进一个方法，实质上想把方法所表示的计算规则传入方法。
 *
 * 回调的概念：
 * 在计算机编程领域，将一个方法作为参数，直接传递给另外一个方法，这种形式称之为"回调"。
 * 作为参数传递的方法,称之为"回调方法"。
 * 比如上述小红类当中的"multiply"方法就是一个回调方法。
 * 回调方法的实现优点是显而易见的，它大大提升了程序的扩展性。
 *
 * 比如上述小明求助方法，只要传入不同的计算规则，小明就能回答不同的计算问题。
 * 不同某些语言，Java是不支持直接回调的，Java的方法不能作为参数直接传递。
 * 但是Java仍然可以实现回调。
 * 典型的就是匿名内部类以及Lambda表达式，尤其是Lambda表达式，它的本质就是一个抽象方法的实现。
 * 虽然将一个Lambda表达式传入方法，表面上是传入功能接口的子类对象，但实质上是传入了一个方法实现。
 * Lambda表达式所实现的功能接口中的抽象方法，就是回调方法。
 *
 * @since 21:46
 * @author wuguidong@cskaoyan.onaliyun.com
 */
public class Demo {
    public static void main(String[] args) {
        LittleMing m = new LittleMing();
        System.out.println("老师开始提问小明同学:");
        System.out.println("先提问加法问题:");
        m.answerAddQuestion(10, 10);

        System.out.println("接下来提问乘法:");
        m.answerMultiplyQuestion(10, 10, new LittleRed());

        System.out.println("接下来老师准备提问幂运算:");
        // 这里需要传入一个表示幂运算的计算规则,用Lambda表达式
        m.answerQuestion(2, 10, Demo::test);
    }

    public static int test(int a, int b) {
        return ((int) Math.pow(a, b));
    }
}

class LittleMing {
    // 小明会加法
    public int add(int num1, int num2) {
        return num1 + num2;
    }

    // 小明自己能够回答加法问题
    public void answerAddQuestion(int num1, int num2) {
        System.out.println("老师我知道，这个加法运算的结果是:" + add(num1, num2));
    }

    // 小明求助于小红童鞋,来计算乘法
    public void answerMultiplyQuestion(int num1, int num2, LittleRed lr) {
        System.out.println("老师我知道，这个乘法运算的结果是:" + lr.multiply(num1, num2));
    }

    public void answerQuestion(int num1, int num2, ICalc ic) {
        System.out.println("老师我知道，这个您要求的运算的结果是:" + ic.calc(num1, num2));
    }
}

// 功能接口表示计算的规则
@FunctionalInterface
interface ICalc {
    int calc(int num1, int num2);
}


// 小红会乘法
class LittleRed {
    public int multiply(int num1, int num2) {
        return num1 * num2;
    }
}